package database

import (
	"fmt"
	"log"
	"time"
	"wms/config"
	"wms/pkg/global"
	"wms/pkg/logger"

	"go.uber.org/zap"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	gormlogger "gorm.io/gorm/logger"
)

const (
	defaultMaxIdleConns    = 10
	defaultMaxOpenConns    = 100
	defaultConnMaxLifetime = 3600
)

// 验证数据库配置
func validateConfig(cfg *config.DatabaseConfig) error {
	if cfg == nil {
		return fmt.Errorf("数据库配置不能为空")
	}
	if cfg.Username == "" {
		return fmt.Errorf("数据库用户名不能为空")
	}
	if cfg.Host == "" {
		return fmt.Errorf("数据库主机不能为空")
	}
	if cfg.Port == 0 {
		return fmt.Errorf("数据库端口不能为0")
	}
	if cfg.Database == "" {
		return fmt.Errorf("数据库名不能为空")
	}

	// 设置连接池默认值
	if cfg.MaxIdle <= 0 {
		cfg.MaxIdle = defaultMaxIdleConns
		logger.Info("使用默认最大空闲连接数", zap.Int("max_idle", defaultMaxIdleConns))
	}
	if cfg.MaxOpen <= 0 {
		cfg.MaxOpen = defaultMaxOpenConns
		logger.Info("使用默认最大打开连接数", zap.Int("max_open", defaultMaxOpenConns))
	}
	if cfg.MaxLifetime <= 0 {
		cfg.MaxLifetime = defaultConnMaxLifetime
		logger.Info("使用默认连接最大生命周期", zap.Int("lifetime_seconds", defaultConnMaxLifetime))
	}

	return nil
}

// InitDB 初始化数据库连接
func InitDB(cfg *config.DatabaseConfig) error {
	// 验证配置
	if err := validateConfig(cfg); err != nil {
		return fmt.Errorf("数据库配置验证失败: %v", err)
	}

	// 构建DSN连接字符串
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&sql_mode=ANSI",
		cfg.Username,
		cfg.Password,
		cfg.Host,
		cfg.Port,
		cfg.Database,
	)

	// 配置GORM日志
	gormLogger := gormlogger.New(
		log.New(log.Writer(), "\r\n", log.LstdFlags),
		gormlogger.Config{
			SlowThreshold:             time.Second,     // 慢SQL阈值
			LogLevel:                  gormlogger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,            // 忽略记录未找到错误
			Colorful:                  true,            // 彩色打印
		},
	)

	// 打开数据库连接
	var err error
	global.DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: gormLogger,
		NowFunc: func() time.Time {
			return time.Now().Local() // 使用本地时间
		},
		DisableForeignKeyConstraintWhenMigrating: true, // 禁用外键约束
	})
	if err != nil {
		return fmt.Errorf("连接数据库失败[%s:%d/%s]: %v", cfg.Host, cfg.Port, cfg.Database, err)
	}

	// 获取底层SQL DB实例
	sqlDB, err := global.DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库实例失败: %v", err)
	}

	// 设置连接池参数
	sqlDB.SetMaxIdleConns(cfg.MaxIdle)
	sqlDB.SetMaxOpenConns(cfg.MaxOpen)
	sqlDB.SetConnMaxLifetime(time.Duration(cfg.MaxLifetime) * time.Second)

	logger.Info("数据库连接成功",
		zap.String("host", cfg.Host),
		zap.Int("port", cfg.Port),
		zap.String("database", cfg.Database),
		zap.Int("max_idle", cfg.MaxIdle),
		zap.Int("max_open", cfg.MaxOpen),
		zap.Int("lifetime", cfg.MaxLifetime),
	)

	return nil
}

// GetDB 获取数据库连接实例
func GetDB() *gorm.DB {
	if global.DB == nil {
		logger.Error("数据库连接未初始化")
		return nil
	}
	return global.DB
}

// Close 关闭数据库连接
func Close() error {
	if global.DB == nil {
		return nil
	}

	sqlDB, err := global.DB.DB()
	if err != nil {
		return fmt.Errorf("获取数据库实例失败: %v", err)
	}

	if err := sqlDB.Close(); err != nil {
		return fmt.Errorf("关闭数据库连接失败: %v", err)
	}

	logger.Info("数据库连接已关闭")
	return nil
}
